import * as Bacon from "..";
import { expect } from "chai";
import { expectPropertyEvents, series, semiunstable, unstable, once, expectError } from "./util/SpecHelper";

describe("Bacon.update", function() {
  describe("works like Bacon.when, but produces a property, and can be defined in terms of a current value", () =>
    expectPropertyEvents(
      function() {
        const [r, _] = ['r', 0]
        const incr  = series(1, [1, _, 1, _, 2, _, 1, _, _, _, 2, _, 1]).filter(x => x !== _);
        const reset = series(1, [_, r, _, _, _, r, _, r, _, r, _, _, _]).filter(x => x === r);
        return Bacon.update(
          0,
          <any>[reset], <any>0,
          <any>[incr], <any>((i: number,c: number) => i+c));
      },
      [0, 1, 0, 1, 3, 0, 1, 0, 0, 2, 3], semiunstable)
  );

  describe("supports the new typed syntax, case 1", () =>
    expectPropertyEvents(
      function() {
        const a = Bacon.later(1, "x");
        const b = Bacon.later(2, "y");

        return Bacon.update(0,
          [a, (acc, x) => acc + x],
          [b, (acc, x) => acc + x]
        );
      },
      [0, "0x", "0xy"], semiunstable)
  );

  describe("supports the new typed syntax, case 2", () =>
    expectPropertyEvents(
      function() {
        const [r,_] = [-1,0];
        const incr  = series(1, [1, _, 1, _, 2, _, 1, _, _, _, 2, _, 1]).filter(x => x !== _);
        const reset = series(1, [_, r, _, _, _, r, _, r, _, r, _, _, _]).filter(x => x === r);
        return Bacon.update(
          0,
          [reset, 0],
          [incr, (i,c) => i+c]
        );
      },
      [0, 1, 0, 1, 3, 0, 1, 0, 0, 2, 3], semiunstable)
  );

  describe("Correctly handles multiple arguments in parameter list, and synchronous sources", () =>
    expectPropertyEvents(
      function() {
        const one = once(1);
        const two = once(2);
        return Bacon.update(
          0,
          <any>[one, two], <any>((i: number, a: number, b: number) => [i,a,b]));
      },
      [0, [0,1,2]], unstable)
  );
  describe("Works with naked streams (not wrapped in array)", () =>
    expectPropertyEvents(
      () => Bacon.update(2, <any>once(1), <any>((a: number,b: number) => a + b)),
      [2, 3], unstable)
  );
  it("Rejects patterns with Properties only", () => {
    expectError("At least one EventStream required", () => {
      Bacon.update(0, 
        <any>[Bacon.constant(0)], <any>(function() {})
      )
    })
  });
  it("toString", () => {
    expect(
      Bacon.update(0, <any>[Bacon.never()], <any>(function() {})
    ).toString()).to.equal("Bacon.update(0,[Bacon.never()],function)")
  });
});
